/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.base.service.impl;

import com.xy.biz.base.domain.bo.BizCodeBO;
import com.xy.biz.base.manager.BizCodeManager;
import com.xy.biz.base.service.BizCodeService;
import com.xy.biz.base.support.bizcode.BizCodeGenerator;
import com.xy.lang.domain.Result;
import com.xy.lang.exception.ObjectNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;

import static com.xy.biz.base.support.bizcode.BizCodeGenerator.ALGORITHM_SERVICE_PREFIX;

/**
 * 
 * 
 * @author zsp
 * @date 2020-8-25
 */
@Service
public class BizCodeServiceImpl implements BizCodeService {

	@Autowired
	private BizCodeManager bizCodeManager;
	@Autowired
	private Map<String, BizCodeGenerator> bizCodeGeneratorMap;

	@Override
	public Result<String> getBizCode(String code, Long tenantId) {
		BizCodeBO bizCodeBO = bizCodeManager.getBizCode(code, tenantId);
		if(null == bizCodeBO) {
			return Result.ofNotFound("未定义业务编码：" + code + ", " + tenantId);
		}
		BizCodeGenerator bizCodeGenerator = bizCodeGeneratorMap.get(ALGORITHM_SERVICE_PREFIX + bizCodeBO.getAlgorithm());
		if(null == bizCodeGenerator) {
			throw new ObjectNotFoundException("未定义的算法：" + bizCodeBO.getAlgorithm());
		}
		for(int i = 0; i < 10; i++) {
			int nextValue = getNextValue(bizCodeBO);
			int affectedRows = bizCodeManager.updateBizCodeIncr(bizCodeBO, nextValue);
			if(affectedRows > 0) {
				return Result.success(decorateCode(bizCodeBO, bizCodeGenerator.generate(bizCodeBO, nextValue)));
			}
			bizCodeManager.getBizCodeCurrentValue(bizCodeBO);
		}

		return Result.fail();
	}

	private String decorateCode(BizCodeBO bizCodeBO, String code) {
		StringBuilder stringBuilder = new StringBuilder(code.length() * 2);
		if(StringUtils.hasText(bizCodeBO.getPrefix())) {
			stringBuilder.append(bizCodeBO.getPrefix());
		}
		stringBuilder.append(code);
		if(StringUtils.hasText(bizCodeBO.getSuffix())) {
			stringBuilder.append(bizCodeBO.getSuffix());
		}
		return stringBuilder.toString();
	}

	private int getNextValue(BizCodeBO bizCodeBO) {
		int currentValue = (null == bizCodeBO.getCurrentValue())
				? (null == bizCodeBO.getNumberOffset()) ? 0 : bizCodeBO.getNumberOffset()
				: bizCodeBO.getCurrentValue();
		int step = (null == bizCodeBO.getNumberStep()) ? 1 : bizCodeBO.getNumberStep();
		return currentValue + step;
	}
	
}
